/**
 * 
 */
package com.netscenery.yang.model;

import java.util.ArrayList;

import org.jdom2.Attribute;
import org.jdom2.Element;

import com.netscenery.util.XMLTag;
import com.netscenery.yang.YangKeyword;
import com.netscenery.yang.YangStatement;
import com.netscenery.yang.designer.MapInfo;
import com.netscenery.yang.parser.YangParserException;

/**
 * @author yanzi
 *
 */
public  class Refine extends ModelElement {
	private String description;
	private String reference;
	private boolean hasConfig = false;
	private boolean isConfig = true;
	private String defaultValue;//leaf or choice
	private boolean hasMandatory = false;
	private boolean mandatory = false;//leaf,anyxml or choice
	private String presence;//container
	private ArrayList<Must> musts;//leaf,leaf-list,list,container or anyxml
	private boolean hasMinElements = false;
	private int minElements;//leaf-list or list
	private boolean hasMaxElements = false;
	private int maxElements;//leaf-list or list
	
	
	/**
	 * 
	 */
	public Refine() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * @param env
	 * @param name
	 * @throws ModelException 
	 */
	public Refine(Env env, String name) throws ModelException {
		super(env, name);
		// TODO Auto-generated constructor stub
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public String getReference() {
		return reference;
	}

	public void setReference(String reference) {
		this.reference = reference;
	}

	public boolean isConfig() {
		return isConfig;
	}

	public void setConfig(boolean isConfig) {
		this.isConfig = isConfig;
		this.hasConfig = true;
	}

	public String getDefaultValue() {
		return defaultValue;
	}

	public void setDefaultValue(String defaultValue) {
		this.defaultValue = defaultValue;
	}

	public boolean isMandatory() {
		return mandatory;
	}

	public void setMandatory(boolean mandatory) {
		this.mandatory = mandatory;
		this.hasMandatory = true;
	}

	public String getPresence() {
		return presence;
	}

	public void setPresence(String presence) {
		this.presence = presence;
	}


	public int getMinElements() {
		return minElements;
	}

	public void setMinElements(int minElements) {
		this.minElements = minElements;
		this.hasMinElements = true;
	}

	public int getMaxElements() {
		return maxElements;
	}

	public void setMaxElements(int maxElements) {
		this.maxElements = maxElements;
		this.hasMaxElements = true;
	}

	/**
	 * ��ȡmust����Ŀ
	 * @return
	 * @see com.netscenery.model.Must
	 */
	public int getMustsNumber(){
		if (null == this.musts){
			return 0;
		}
		return this.musts.size();
	}
	/**
	 * ���ָ������ƴ���Must
	 * @param name
	 * @return
	 * @throws ModelException 
	 * @see com.netscenery.model.Must
	 */
	public Must createMust(String name) throws ModelException{
		if (null == name){
			return null;
		}
		
		return new Must(newSubEnv(),name);
	}
	/**
	 * ���һ��Must
	 * @param n
	 * @return
	 * @see com.netscenery.model.Must
	 */
	public boolean addMust(Must n){
		if(null == n){
			return false;
		}
		
		if (null == this.musts){
			this.musts = new ArrayList<Must>(1);
		}
		if (null != this.getMust(n.getName())){
			return false;
		}
		return this.musts.add(n);
		

	}
	/**
	 * �����Ż�ȡMust
	 * @param index
	 * @return
	 * @see com.netscenery.model.Must
	 */
	public Must getMust(int index){
		if (null == this.musts){
			return null;
		}
		if (index >= this.musts.size()){
			return null;
		}
		return this.musts.get(index);
	}
	/**
	 * �����ƻ�ȡMust
	 * @param name
	 * @return
	 * @see com.netscenery.model.Must
	 */
	public Must getMust(String name){
		if (null == this.musts){
			return null;
		}
		int size = musts.size();
		if (size <= 0){
			return null;
		}
		
		for (int i = 0; i < size; i++){
			Must n = this.musts.get(i);
			if (null != n){
				if (n.getName().equals(name)){
					return n;
				}
			}
		}
		return null;
	}
	/**
	 * ������ɾ��Must
	 * @param index
	 * @return Must
	 * @see com.netscenery.model.Must
	 */
	public Must removeMust(int index){
		if (null == this.musts){
			return null;
		}
		if (index >= this.musts.size()){
			return null;
		}
		return this.musts.remove(index);
	}
	/**
	 * ������ɾ��Must
	 * @param name
	 * @return Must
	 * @see com.netscenery.model.Must
	 */
	public Must removeMust(String name){
		if (null == this.musts){
			return null;
		}
		int size = musts.size();
		if (size <= 0){
			return null;
		}
		
		
		for (int i = 0; i < size; i++){
			Must n = this.musts.get(i);
			if (null != n){
				if (n.getName().equals(name)){
					return musts.remove(i);
				}
			}
		}
		return null;
	}
	public boolean isHasConfig() {
		return hasConfig;
	}

	public void setHasConfig(boolean hasConfig) {
		this.hasConfig = hasConfig;
	}

	public boolean isHasMandatory() {
		return hasMandatory;
	}

	public void setHasMandatory(boolean hasMandatory) {
		this.hasMandatory = hasMandatory;
	}

	public boolean isHasMinElements() {
		return hasMinElements;
	}

	public void setHasMinElements(boolean hasMinElements) {
		this.hasMinElements = hasMinElements;
	}

	public boolean isHasMaxElements() {
		return hasMaxElements;
	}

	public void setHasMaxElements(boolean hasMaxElements) {
		this.hasMaxElements = hasMaxElements;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#toYang()
	 */
	@Override
	public YangStatement toYang() {
		YangStatement refine = new YangStatement(YangKeyword.REFINE.getKeyword(),this.name);
		
		if (!isNullString( this.description)){
			YangStatement descr = new YangStatement(YangStatement.YANG_STATEMENT_DESCRIPTION,this.description);
			refine.addChild(descr);
		}
		if (!isNullString(this.reference)){
			YangStatement ref = new YangStatement(YangStatement.YANG_STATEMENT_REFERENCE,this.getReference());
			refine.addChild(ref);
		}
		if(isHasConfig()){
			YangStatement config = new YangStatement(
					YangStatement.YANG_STATEMENT_CONFIG,
					(true == this.isConfig) ? "true" : "false");
			refine.addChild(config);
		}
		if (!isNullString(this.defaultValue)){
			YangStatement dv = new YangStatement(YangStatement.YANG_STATEMENT_DEFAULT
					,this.getDefaultValue());
			refine.addChild(dv);
		}
		if (isHasMandatory()){
			YangStatement mandatory = new YangStatement(YangStatement.YANG_STATEMENT_MANDATORY
					,(true == this.isMandatory())?"true":"false");
			refine.addChild(mandatory);
		}
		if (!isNullString(this.presence)){
			YangStatement presence = new YangStatement(YangStatement.YANG_STATEMENT_PRESENCE,this.getPresence());
			refine.addChild(presence);
		}
		
		if (null != this.musts){
			int size = this.getMustsNumber();
			
			for (int i = 0; i < size; i++){
				Must must = getMust(i);
				if (null != must){
					YangStatement muststat = must.writeYang();
					if (null != muststat){
						refine.addChild(muststat);
					}
				}
			}
			
		}
		
		if (isHasMinElements()){
			YangStatement minElements = new YangStatement(YangStatement.YANG_STATEMENT_MINELEMENTS
					,new Integer(this.getMinElements()).toString());
			refine.addChild(minElements);
		}
		
		if (isHasMaxElements()){
			YangStatement maxElements = new YangStatement(YangStatement.YANG_STATEMENT_MAXELEMENTS
					,new Integer(this.getMaxElements()).toString());
			refine.addChild(maxElements);
		}
		
		return refine;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#toYin()
	 */
	@Override
	public Element toYin() {
		Element refine = new Element(YangKeyword.REFINE.getKeyword(),env.getNs());
		Attribute targetNode = new Attribute("target-node",this.name);
		refine.setAttribute(targetNode);
		
		if (!isNullString( this.description)){
			Element descr = new Element(YangStatement.YANG_STATEMENT_DESCRIPTION,env.getNs());
			Element text = new Element(XMLTag.XML_TAG_TEXT,env.getNs());
			text.setText(this.description);
			descr.addContent(text);
			refine.addContent(descr);
		}
		if (!isNullString(this.reference)){
			Element ref = new Element(YangStatement.YANG_STATEMENT_REFERENCE,env.getNs());
			Element text = new Element(XMLTag.XML_TAG_TEXT,env.getNs());
			text.setText(this.reference);
			ref.addContent(text);
			refine.addContent(ref);
		}
		if(isHasConfig()){
			Element config = new Element(
					YangStatement.YANG_STATEMENT_CONFIG,env.getNs());
			Attribute value = new Attribute(YangKeyword.VALUE.getKeyword(),
					(true == this.isConfig) ? "true" : "false");
			config.setAttribute(value);
			refine.addContent(config);
		}
		if (!isNullString(this.defaultValue)){
			Element dv = new Element(YangStatement.YANG_STATEMENT_DEFAULT,env.getNs());
			Attribute value = new Attribute(YangKeyword.VALUE.getKeyword(),
					this.getDefaultValue());		
			dv.setAttribute(value);
			refine.addContent(dv);
		}
		if (isHasMandatory()){
			Element mandatory = new Element(
					YangStatement.YANG_STATEMENT_MANDATORY,env.getNs());
			Attribute value = new Attribute(YangKeyword.VALUE.getKeyword(),
					(true == this.isMandatory()) ? "true" : "false");
			mandatory.setAttribute(value);
			refine.addContent(mandatory);
		}
		if (!isNullString(this.presence)){
			Element presence = new Element(YangStatement.YANG_STATEMENT_PRESENCE,env.getNs());
			Attribute value = new Attribute(YangKeyword.VALUE.getKeyword(), this.getPresence());
			presence.setAttribute(value);
			refine.addContent(presence);
		}
		
		if (null != this.musts){
			int size = this.getMustsNumber();
			
			for (int i = 0; i < size; i++){
				Must must = getMust(i);
				if (null != must){
					Element muststat = must.writeYin();
					if (null != muststat){
						refine.addContent(muststat);
					}
				}
			}
			
		}
		
		if (isHasMinElements()){
			Element minElements = new Element(YangStatement.YANG_STATEMENT_MINELEMENTS,env.getNs());
			Attribute value = new Attribute(YangKeyword.VALUE.getKeyword()
					,new Integer(this.getMinElements()).toString());
			minElements.setAttribute(value);
			refine.addContent(minElements);
		}
		
		if (isHasMaxElements()){
			Element maxElements = new Element(YangStatement.YANG_STATEMENT_MAXELEMENTS,env.getNs());
			Attribute value = new Attribute(YangKeyword.VALUE.getKeyword()
					,new Integer(this.getMaxElements()).toString());
			maxElements.setAttribute(value);
			refine.addContent(maxElements);
		}
		
		return refine;
		
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#toXML()
	 */
	@Override
	public Element toXML() {
		// TODO Auto-generated method stub
		return null;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#readXML(org.jdom2.Element)
	 */
	@Override
	public int readXML(Element element) throws ModelException {
		// TODO Auto-generated method stub
		return 0;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#readYin(org.jdom2.Element)
	 */
	@Override
	public int readYin(Element element) throws ModelException {
		
		if (null == element){
			return MODELELEMENT_OK;
		}
		
		
		// ����
		if (element.getName().equals(YangStatement.YANG_STATEMENT_DESCRIPTION)) {
			Element text = element.getChild(XMLTag.XML_TAG_TEXT,env.getNs());
			if (null == text){
				return MODELELEMENT_FAIL;
			}
			this.setDescription(text.getText());
		}
		// reference
		else if (element.getName().equals(YangStatement.YANG_STATEMENT_REFERENCE)) {
			Element text = element.getChild(XMLTag.XML_TAG_TEXT,env.getNs());
			if (null == text){
				return MODELELEMENT_FAIL;
			}
			this.setReference(text.getText());
		}

		// config
		else if (element.getName().equals(YangStatement.YANG_STATEMENT_CONFIG)) {
			String value= element.getAttributeValue(YangKeyword.VALUE.getKeyword());
			if (null != value){
				if (value.equals("true")){
					this.setConfig(true);
				}
				else if (value.equals("false")){
					this.setConfig(false);
				}
				else {
					return MODELELEMENT_FAIL;
				}
			}
			else {
				return MODELELEMENT_FAIL;
			}
		}
		// presence
		else if (element.getName().equals(YangStatement.YANG_STATEMENT_PRESENCE)) {
			String value= element.getAttributeValue(YangKeyword.VALUE.getKeyword());
			if(isNullString(value)){
				return MODELELEMENT_FAIL;
			}
			this.setPresence(value);
		}
		// mandatory
		else if (element.getName().equals(YangStatement.YANG_STATEMENT_MANDATORY)) {
			String value= element.getAttributeValue(YangKeyword.VALUE.getKeyword());
			
			if (null != value) {
				if (value.equals("true")) {
					this.setMandatory(true);
				} else if (value.equals("false")) {
					this.setMandatory(false);
				} else {
					return MODELELEMENT_FAIL;
				}
			}
		}
		// default
		else if (element.getName().equals(YangStatement.YANG_STATEMENT_DEFAULT)) {
			String value= element.getAttributeValue(YangKeyword.VALUE.getKeyword());
			this.setDefaultValue(value);
		}
		// maxElements
		else if (element.getName().equals(YangStatement.YANG_STATEMENT_MAXELEMENTS)) {
			String value= element.getAttributeValue(YangKeyword.VALUE.getKeyword());
			if (!isNullString(value)){
				this.setMaxElements(new Integer(value).intValue());
			}	
		}
		// minElements
		else if (element.getName().equals(YangStatement.YANG_STATEMENT_MINELEMENTS)) {
			String value= element.getAttributeValue(YangKeyword.VALUE.getKeyword());
			if(!isNullString(value)){
				this.setMinElements(new Integer(value).intValue());
			}		
		}
		// must
		else if (element.getName().equals(
						YangStatement.YANG_STATEMENT_MUST)) {
			Must must = (Must)ModelElement.parseYin(newSubEnv(), element);	
			if (null != must){
				this.addMust(must);
			}
		}
		else {
			return MODELELEMENT_FAIL;
		}

		return MODELELEMENT_OK;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#readYANG(com.netscenery.yang.YangStatement)
	 */
	@Override
	public int readYANG(YangStatement statement) throws YangParserException, ModelException {
		if (null == statement){
			return MODELELEMENT_OK;
		}
		
		String value = statement.getArgument();
		// ����
		if (statement.getKeyword().equals(
				YangStatement.YANG_STATEMENT_DESCRIPTION)) {
			this.setDescription(value);
		}
		// reference
		else if (statement.getKeyword().equals(
				YangStatement.YANG_STATEMENT_REFERENCE)) {
			this.setReference(value);
		}

		// config
		else if (statement.getKeyword().equals(
				YangStatement.YANG_STATEMENT_CONFIG)) {
			if (null != value) {
				if (value.equals("true")) {
					this.setConfig(true);
				} else if (value.equals("false")) {
					this.setConfig(false);
				} else {
					return MODELELEMENT_FAIL;
				}
			}
		}
		// presence
		else if (statement.getKeyword().equals(
				YangStatement.YANG_STATEMENT_PRESENCE)) {
			this.setPresence(value);
		}
		// mandatory
		else if (statement.getKeyword().equals(
				YangStatement.YANG_STATEMENT_MANDATORY)) {

			if (null != value) {
				if (value.equals("true")) {
					this.setMandatory(true);
				} else if (value.equals("false")) {
					this.setMandatory(false);
				} else {
					return MODELELEMENT_FAIL;
				}
			}
		}
		// default
		else if (statement.getKeyword().equals(
				YangStatement.YANG_STATEMENT_DEFAULT)) {
			
			this.setDefaultValue(value);
		}
		// maxElements
		else if (statement.getKeyword().equals(
				YangStatement.YANG_STATEMENT_MAXELEMENTS)) {
			
			this.setMaxElements(new Integer(value).intValue());
		}
		// minElements
		else if (statement.getKeyword().equals(
				YangStatement.YANG_STATEMENT_MINELEMENTS)) {
			
			this.setMinElements(new Integer(value).intValue());
		}
		// must
		else if (statement.getKeyword().equals(
						YangStatement.YANG_STATEMENT_MUST)) {
			Must must = (Must)ModelElement.parseYANG(newSubEnv(), statement);	
			if (null != must){
				this.addMust(must);
			}
		}
		else {
			return MODELELEMENT_FAIL;
		}

		return MODELELEMENT_OK;
	}

	@Override
	public Validator validate() {
		// TODO Auto-generated method stub
		return super.validate();
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#isFieldMandatory(java.lang.String)
	 */
	@Override
	public boolean isFieldMandatory(String field) {
		// TODO Auto-generated method stub
		return false;
	}

	/* (non-Javadoc)
	 * @see com.netscenery.yang.model.ModelElement#getMapInfo()
	 */
	@Override
	public MapInfo getMapInfo() throws SecurityException, NoSuchMethodException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void update() {
		// TODO Auto-generated method stub
		
	}

}
